package edu.mercer.sse.tasks.web;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.util.concurrent.Callable;
import java.util.logging.Level;

import edu.mercer.sse.logging.LoggerCustom;
import edu.mercer.sse.tlocal.ThreadObjectProxification;
import edu.mercer.sse.tlocal.ThreadObjectProxy;

/**
 * Accepts URL parameter for download of content. Defaults to random URL.<p>
 * 
 * Demonstration of thread-specific storage using thread-global StringBuilder 
 * 	instance(s).<p>
 *
 * {@link #call()} Downloads URL and appends to thread-global StringBuilder
 * 	instances.<p>
 *
 * @see ThreadObjectProxification
 * @see Callable
 */

public class URLRetrieval implements Callable<String>
{
	/**
	 * String of Random URL provider.<p>
	 * 
	 * Random URL provided with redirect for each access of this URL.<p> 
	 */
	
	private final static String RANDOM_URL_SITE_DEFAULT = 
			"http://www.randomwebsite.com/cgi-bin/random.pl";

	
	/** String URL set to default, optionally overridden by constructor */
	
	private String _site = RANDOM_URL_SITE_DEFAULT;


	/**
	 * Thread-global object instances.<p>
	 * 
	 * Multiple instances of StringBuilder are permitted. Each is mapped
	 * 	using String key and is global and accessible to this thread only.<p>
	 * 
	 * Must wait to initialize: if init. upon construction, usually done
	 * 	in single-threaded environment when Callable created.<p> 
	 * 
	 * Must wait until are in additional thread if any: when the call/run 
	 * 	execution begins; i.e., the download of the URL.<p>
	 * 
	 * Using Interface as type: programming to interface, not object 
	 * 	specifications.<p>
	 */
	
	private ThreadObjectProxification<String,StringBuilder> 
		_thrdPrxStringBuilder; // = ThreadObjectProxy.factory();

	/**
	 * Supplied by constructor.<p>
	 * 
	 * Serves as key, allowing for multiple object instances of same type as 
	 * 	thread-globals.<p> 
	 */
	
	private Integer _threadGlobalProxyID = 0;
	
	
	/** 
	 * StringBuilder as local reference to thread-global StringBuilder 
	 * instance 
	 */
	
	private StringBuilder _results;

	
	/**
	 * Constructor.<p>
	 * 
	 * Uses default random website URL source.<p>
	 * 
	 * @param randomURLNumber - Integer appended to key for thread-global 
	 * 	objects used.
	 */
	
	public URLRetrieval( final Integer randomURLNumber )
	{
		super();

		//init( randomURLNumber );
		
		_threadGlobalProxyID = randomURLNumber;
		
	}//constructor
	
	
	/**
	 * Constructor.<p>
	 * 
	 * Uses specified website URL as source for download.<p>
	 * 
	 * @param websiteUrlStr - String website URL to download
	 * 
	 * @param randomURLNumber - Integer appended to key for thread-global 
	 * 	objects used.
	 */
	
	public URLRetrieval( final String websiteUrlStr, 
 			   		     final Integer randomURLNumber )
	{
		super();
		
		checkNotNull( websiteUrlStr, 
				"null website url String argument" );

		checkArgument( websiteUrlStr.length() > 0, 
				"zero length website url String argument" );
		
		_site = websiteUrlStr;
		
		_threadGlobalProxyID = randomURLNumber;

		//init( randomURLNumber );
		
	}//constructor
	

	/**
	 * Initialization.<p>
	 * 
	 * Purposes:<p>
	 * 
	 * <ol>
	 * <li>Initialization of Thread Proxy Object: String Builder thread-global
	 * 	object proxy instance for this thread.
	 * 
	 * <li>Creates initial instance of StringBuilder in thread-global object 
	 * 	cache. Subsequent 'set' calls disregarded for this thread and existing 
	 * 	reference is returned.
	 * </ol>
	 * 
	 * Should not be called until running in thread; i.e., download of URL or
	 * 	the {@link #call()}<p>
	 */
	
	private void init()
	{
		_thrdPrxStringBuilder = ThreadObjectProxy.factory();
		
		_results = _thrdPrxStringBuilder.set( "website-contents" 
				  + _threadGlobalProxyID,
				  
				  new StringBuilder() )

			.get( "website-contents" + _threadGlobalProxyID );
		
	}//method	
	

	/**
	 * Download URL, appending contents to thread-global StringBuilder 
	 * 	instance.<p>
	 * 
	 * @return  String - url accessed and size of content retrieved.<p>  
	 * 
	 * @see #downloadURL()
	 */
	
	@Override
	public String call() 
	{
		init();
		
		_results.append( new DownloadURLFunction().apply( _site ) );
		
		LoggerCustom.obtainLog( "test_threadproxystringbuilder", Level.ALL)
			.fine("downloaded total: " + _results.length() );
		
		return _site + " downloaded. Size: " + _results.length();
		
	}//method
		
	
}//class